package service

import (
	"admin100/app/dao"
	"admin100/app/model"
	"admin100/library/define"
	"admin100/library/define/defErr"
	"database/sql"

	menutree "github.com/azhengyongqin/golang-tree-menu"
	"github.com/gogf/gf/util/gconv"
)

var Menu = menuService{}

type menuService struct{}

type ChannelList []item

type item struct {
	*model.MyadminMenu
	Children []*childrenItem
}

type childrenItem struct {
	*model.MyadminMenu
	ChildrenItem []interface{}
}

func (m *menuService) List() ChannelList {
	menu, err := dao.MyadminMenu.All()
	defErr.IfPanic(err, define.DataOptFail)

	var list = ChannelList{}
	for _, v := range menu {
		if v.ParentId == 0 {
			list = append(list, item{MyadminMenu: v, Children: []*childrenItem{}})
		}
	}

	//
	for i, subItem := range list {
		for _, data := range menu {
			if data.ParentId == subItem.Id {
				subItem.Children = append(subItem.Children, &childrenItem{MyadminMenu: data, ChildrenItem: []interface{}{}})
				list[i] = subItem
			}
		}
	}

	return list
}

func (m *menuService) Add(req *model.MyadminMenuAddReq) bool {

	if has := dao.MyadminMenu.HasByName(req.Name); has {
		defErr.Panic(define.MenuNameExist)
	}
	if has := dao.MyadminMenu.HasByTitle(req.Title); has {
		defErr.Panic(define.MenuTitleExist)
	}
	if req.ParentId > 0 {
		if has := dao.MyadminMenu.HasByParentId(req.ParentId); !has {
			defErr.Panic(define.MenuPidNotExist)
		}
	}
	if has := dao.MyadminMenu.HasBySeq(req.Seq); has {
		defErr.Panic(define.MenuSeqExist)
	}

	if _, err := dao.MyadminMenu.Save(req); err != nil {
		defErr.Panic(define.DataOptFail)
	}

	return true
}

func (m *menuService) Edit(req *model.MyadminMenuEditReq) bool {

	var data = &model.MyadminMenu{}
	err := dao.MyadminMenu.Where(dao.MyadminMenu.Columns.Id, req.Id).Struct(data)
	if err != nil || err != sql.ErrNoRows {
		defErr.Panic(define.MenuNotExist)
	}

	if req.Name != data.Name {
		if has := dao.MyadminMenu.HasByName(req.Name); has {
			defErr.Panic(define.MenuNameExist)
		}
	}
	if req.Title != data.Title {
		if has := dao.MyadminMenu.HasByTitle(req.Title); has {
			defErr.Panic(define.MenuTitleExist)
		}
	}
	if req.ParentId > 0 && uint(req.ParentId) != data.ParentId {
		// 父结点不可以再被移动
		//if data.ParentId != uint(req.ParentId) {
		var pData = &model.MyadminMenu{}
		pErr := dao.MyadminMenu.Where(dao.MyadminMenu.Columns.Id, req.ParentId).Struct(pData)
		if pErr != nil && pErr != sql.ErrNoRows {
			defErr.Panic(define.MenuPidNotExist)
		}
		if data.ParentId == 0 {
			defErr.Panic(define.IsParentNode)
		}
		if pData.ParentId != 0 {
			defErr.Panic(define.ParentIllegal)
		}

	}

	if uint(req.Seq) != data.Seq {
		if has := dao.MyadminMenu.HasBySeq(req.Seq); has {
			defErr.Panic(define.MenuSeqExist)
		}
	}

	if _, err := dao.MyadminMenu.Save(req); err != nil {
		defErr.Panic(define.DataOptFail)
	}
	return true
}

func (m *menuService) Del(menuId int64) bool {
	if menuId < 1 {
		return true
	}

	if _, err := dao.MyadminMenu.Delete(dao.MyadminMenu.Columns.Id, menuId); err != nil {
		defErr.Panic(define.DataOptFail)
	}
	return true
}

func (m *menuService) FetchParentMenus() []*model.MyadminMenu {
	r, err := dao.MyadminMenu.FieldsEx(
		dao.MyadminMenu.Columns.Seq,
		dao.MyadminMenu.Columns.ParentId,
		dao.MyadminMenu.Columns.Name,
		dao.MyadminMenu.Columns.Icon,
	).Where(dao.MyadminMenu.Columns.ParentId, 0).All()
	defErr.IfPanic(err, define.DataOptFail)

	return r
}

func (m *menuService) FetchParentMenuById(menuId int64) *model.MyadminMenu {
	r, err := dao.MyadminMenu.FieldsEx(
		dao.MyadminMenu.Columns.Seq,
		dao.MyadminMenu.Columns.Name,
		dao.MyadminMenu.Columns.Icon,
	).Where(dao.MyadminMenu.Columns.Id, menuId).FindOne()
	defErr.IfPanic(err, define.DataOptFail)

	return r
}

func (m *menuService) relateMenuListParent(menuList []*model.MyadminMenu) {
	for _, menu := range menuList {
		if menu.ParentId > 0 {
			pMenu, err := dao.MyadminMenu.Where(dao.MyadminMenu.Columns.ParentId, menu.ParentId).FindOne()
			defErr.IfPanic(err, define.DataOptFail)
			menu.Parent = pMenu
		}
	}
}

func (m *menuService) GetMenuListByUserId(u *model.MyadminUser) []*model.MyadminMenu {
	if u.IsSuper == 1 {
		menu, err := dao.MyadminMenu.Order(dao.MyadminMenu.Columns.Id + " desc").FindAll()
		defErr.IfPanic(err, define.DataOptFail)

		m.relateMenuListParent(menu)
		return menu
	} else {
		menu, err := dao.MyadminMenu.As("T0").Fields("DISTINCT T0.*").
			InnerJoin(dao.MyadminRoleMenuRel.Table, "T2",
				"T0."+dao.MyadminMenu.Columns.Id+"=T2."+dao.MyadminRoleMenuRel.Columns.MenuId).
			InnerJoin(dao.MyadminRoleUserRel.Table, "T1",
				"T2."+dao.MyadminRoleMenuRel.Columns.RoleId+"=T1."+dao.MyadminRoleUserRel.Columns.RoleId).
			Where("T1."+dao.MyadminRoleUserRel.Columns.UserId+"=?", u.Id).Order("T0.id desc").FindAll()
		defErr.IfPanic(err, define.DataOptFail)
		return menu
	}

	return nil
}

func (m *menuService) TranMenuList2MenuTree(menuList []*model.MyadminMenu) interface{} {
	var iNodes []menutree.INode

	for _, v := range menuList {
		var point model.MyadminMenuNode
		if err := gconv.Struct(v, &point); err != nil {
			defErr.Panic(define.Fail, err.Error())
		} else {
			iNodes = append(iNodes, &point)
		}

	}
	res := menutree.GenerateTree(iNodes, nil)
	// fmt.Print(res)
	// menuTree := make([]*model.MyadminMenu, 0)
	// var mapMenu = make(map[uint][]*model.MyadminMenu)
	// for _, v := range menuList {
	// 	if v.ParentId == 0 && (isDealShow == false || v.IsShow == 1) {
	// 		// 先得到根目录菜单
	// 		menuTree = append(menuTree, v)
	// 	}

	// }

	// // set mapMenu
	// for _, v := range menuList {
	// 	if v.ParentId > 0 && (isDealShow == false || v.IsShow == 1) {
	// 		mapMenu[v.ParentId] = append(mapMenu[v.ParentId], v)
	// 	}
	// }

	// for _, v := range menuList {
	// 	if v.ParentId == 0 && (isDealShow == false || v.IsShow == 1) {
	// 		v.Children = mapMenu[v.Id]
	// 	}
	// }

	return res
}
